<?php


namespace EchoPHP\Database;

use EchoPHP\Database\TuxedoDriver\TuxedoMultiTransactionStatement;
use EchoPHP\Database\TuxedoDriver\TuxedoTransactionStatement;
use InvalidArgumentException;

class DatabaseManager {
    /**
     * 应用程序容器实例
     * @var EchoPHP\Foundation\Application
     */
    protected $app;

    /**
     * 数据库连接工厂类实例
     * @var ConnectionFactory
     */
    protected $factory;

    /**
     * 数据库连接实例集合
     * @var array
     */
    protected $connections = [];

    public function __construct($app, ConnectionFactory $factory) {
        $this->app = $app;
        $this->factory = $factory;
    }

    /**
     * 通过DatabaseManager类动态调用数据库连接里面的方法
     * @param $method
     * @param $parameters
     * @return mixed
     */
    public function __call($method, $parameters) {
        return $this->connect()->$method(...$parameters);
    }

    /**
     * 连接数据库
     * @param null $name
     * @return mixed
     */
    public function connect($name = null) {
        $name = $this->getConnectionName($name);
        if (!isset($this->connections[$name])) {
            $this->connections[$name] = $this->makeConnection($name);
        }

        return $this->connections[$name];
    }

    /**
     * 关闭连接
     * @param null $name
     */
    public function disconnect($name = null) {
        $name = $this->getConnectionName($name);
        if (isset($this->connections[$name])) {
            $this->connections[$name]->disconnect();
        }
    }

    /**
     * 重新连接
     * @param null $name
     * @return mixed
     */
    public function reconnect($name = null) {
        $name = $this->getConnectionName($name);

        $this->disconnect($name);
        if (!isset($this->connections[$name])) {
            return $this->connect($name);
        }
        $connection = $this->makeConnection($name);
        return $this->connections[$name]->setPdo($connection->getConnector());
    }

    /**
     * 创建数据库连接实例
     * @param $name
     * @return Connections\Connection
     */
    protected function makeConnection($name) {
        $config = $this->getConfiguration($name);

        return $this->factory->make($config);
    }

    /**
     * 根据数据库标识获取数据库配置定义
     * @param $name
     * @return array
     */
    protected function getConfiguration($name) {
        $name = $this->getConnectionName($name);

        $config = $this->app['config']['database.connections'];
        if (!isset($config[$name])) {
            throw new InvalidArgumentException('Database [' . $name . ']not configured');
        }
        return $config[$name];
    }

    /**
     * 获取默认数据库连接名称,未定义则获取默认名称
     * @param string $name
     * @return string
     */
    protected function getConnectionName($name = null) {
        if (!empty($name)) {
            return $name;
        }
        return $this->app['config']['database.default'];
    }

    public function multiTransaction(TuxedoTransactionStatement ...$tuxedoTransactionStatements) {
        return new TuxedoMultiTransactionStatement($tuxedoTransactionStatements);
    }

}